"use strict"

const db = require("../lib/mysql")
const { success, fail, test, render } = require("../lib/result")
const PasswordHash = require("node-phpass").PasswordHash
const passwordHash = new PasswordHash(8, true, 5)

const { setToken, verifyToken } = require("../lib/token")

/* 注册 */

const register = async function(ctx, next) {
  let query = ctx.request.body || ctx.request.query
  const dic = {
    name: {
      name: "用户名",
      type: "String",
      required: true
    },
    password: {
      name: "密码",
      type: "String",
      required: true
    },
    mail: {
      name: "邮箱",
      type: "String",
      required: true
    },
    url: {
      name: "个人主页",
      type: "String",
      required: false
    },
    screenName: {
      name: "昵称",
      type: "String",
      required: false
    },
    created: {
      name: "创建时间",
      type: "Number",
      required: false,
      default: () => parseInt(new Date().valueOf() / 1000)
    },
    activated: {
      name: "活跃时间",
      type: "Number",
      required: false,
      default: () => parseInt(new Date().valueOf() / 1000)
    }
  }

  const queryResult = test(query, dic)
  if (queryResult.success) {
    /* 校验通过，将转化过默认值的 query 返回回来 */
    query = queryResult.msg
    query.password = await passwordHash.HashPassword(query.password)
    /* 判断 name 字段是否有重复 */
    let isExist = await db.query(
      `SELECT * FROM js_users WHERE name = '${query.name}'`
    )
    isExist = [...isExist].length > 0
    if (!isExist) {
      if (!query.screenName) {
        query.screenName = query.name
      }
      query.group = "subscriber"
      const renderData = render(query)
      const sql = `INSERT INTO js_users (${renderData.key.join(
        ", "
      )}) VALUES (${renderData.val.join(", ")})`
      const res = await db.query(sql)
      if (res.insertId > 0) {
        return success({
          id: res.insertId
        })
      } else {
        return fail(24, res)
      }
    } else {
      return fail(23, "用户名已存在")
    }
  } else {
    return fail(22, queryResult.msg)
  }
}

/* 登录 */

const login = async function(ctx, next) {
  let query = ctx.request.body || ctx.request.query
  let dic = {
    name: {
      name: "用户名",
      type: "String",
      required: true
    },
    password: {
      name: "密码",
      type: "String",
      required: true
    }
  }
  const queryResult = test(query, dic)
  if (queryResult.success) {
    const sql = `SELECT uid, name, url, mail, screenName as nickname, activated as last_login, wx_username, wx_avatar, wx_info, password FROM js_users WHERE 1 LIMIT 1`
    const res = await db.query(sql)

    if (res instanceof Array && res.length > 0) {
      const isPass = await passwordHash.CheckPassword(
        query.password,
        res[0]["password"]
      )

      if (isPass) {
        const userInfo = res[0]
        delete userInfo.password
        /* 更新一下 token */
        const token = setToken(userInfo.name, userInfo.uid, 72)
        userInfo.token = token
        return success(userInfo)
      } else {
        return fail(886, "用户名或密码错误")
      }
    } else {
      return fail(886, "用户名或密码错误")
    }
  } else {
    return fail(22, queryResult.msg)
  }
}

/* 获取用户资料，有 userId 和 token 两种查找方式 */

const user = async function(ctx, next) {
  let userId = ctx.params.id
  if (userId > 0) {
    const sql = `SELECT uid, name, url, mail, screenName as nickname, activated as last_login, wx_username, wx_avatar, wx_info FROM js_users WHERE uid = ${userId} LIMIT 1`
    let res = await db.query(sql)
    if (res instanceof Array && res.length > 0) {
      return success(res)
    } else {
      return fail(26, "没有找到这个用户")
    }
  } else {
    return fail(25, "请输入正确的用户ID")
  }
}

/* 检查 token */

const check = async function(ctx, next) {
  let token = ctx.request.query.token
  console.log(token)
  if (token) {
    let userInfo = verifyToken(token, true)
    if (userInfo) {
      return success(userInfo)
    } else {
      return fail(26, "没有找到这个用户")
    }
  } else {
    return fail(25, "请输入正确的用户token")
  }
}

module.exports = {
  register,
  login,
  user,
  check,
  passwordHash
}
